// ds1302.c
#include "ds1302.h"
#include "esp_log.h"
#include <string.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

// 定义DS1302连接的GPIO引脚
#define DS1302_CLK_GPIO   GPIO_NUM_13
#define DS1302_DAT_GPIO   GPIO_NUM_14
#define DS1302_RST_GPIO   GPIO_NUM_15

// 延时函数（微秒级）
static void ds1302_delay_us(uint32_t us) {
    ets_delay_us(us);
}
// BCD转十进制
static uint8_t bcd_to_dec(uint8_t bcd) {
    return ((bcd >> 4) * 10) + (bcd & 0x0F);
}
// 十进制转BCD码
static uint8_t dec_to_bcd(uint8_t dec) {
    return ((dec / 10) << 4) + (dec % 10);
}
// 初始化DS1302 GPIO引脚
esp_err_t ds1302_init(void) {
    // 配置CLK引脚
    gpio_set_direction(DS1302_CLK_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_level(DS1302_CLK_GPIO, 0);

    // 配置RST引脚
    gpio_set_direction(DS1302_RST_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_level(DS1302_RST_GPIO, 0);

    // 配置DAT引脚（默认输入）
    gpio_set_direction(DS1302_DAT_GPIO, GPIO_MODE_INPUT);

    return ESP_OK;
}

// 向DS1302写入一个字节
static void ds1302_write_byte(uint8_t data) {
    uint8_t i;

    // 配置DAT为输出模式
    gpio_set_direction(DS1302_DAT_GPIO, GPIO_MODE_OUTPUT);

    // 写入8位数据（低位在前）
    for (i = 0; i < 8; i++) {
        gpio_set_level(DS1302_DAT_GPIO, (data >> i) & 0x01);
        ds1302_delay_us(2);
        gpio_set_level(DS1302_CLK_GPIO, 1);
        ds1302_delay_us(2);
        gpio_set_level(DS1302_CLK_GPIO, 0);
        ds1302_delay_us(2);
    }
}

// 从DS1302读取一个字节
static uint8_t ds1302_read_byte(void) {
    uint8_t i, data = 0;

    // 配置DAT为输入模式
    gpio_set_direction(DS1302_DAT_GPIO, GPIO_MODE_INPUT);

    // 读取8位数据（低位在前）
    for (i = 0; i < 8; i++) {
        data |= (gpio_get_level(DS1302_DAT_GPIO) << i);
        gpio_set_level(DS1302_CLK_GPIO, 1);
        ds1302_delay_us(2);
        gpio_set_level(DS1302_CLK_GPIO, 0);
        ds1302_delay_us(2);
    }

    return data;
}

// 读取DS1302寄存器
// ds1302.c（读取寄存器，地址自动转换为读命令）
uint8_t ds1302_read_register(uint8_t reg_addr) {
    // reg_addr 为写地址（如0x80），转为读地址（0x81）
    uint8_t data;
    gpio_set_level(DS1302_RST_GPIO, 1);
    ets_delay_us(10);
    ds1302_write_byte(reg_addr | 0x01);  // 最低位设为1（读命令）
    data = ds1302_read_byte();
    gpio_set_level(DS1302_RST_GPIO, 0);
    ets_delay_us(10);
    return data;
}

// ds1302.c（写入寄存器，地址自动转换为写命令）
void ds1302_write_register(uint8_t reg_addr, uint8_t data) {
    // reg_addr 为写地址（如0x80），无需修改最低位
    gpio_set_level(DS1302_RST_GPIO, 1);
    ets_delay_us(10);
    ds1302_write_byte(reg_addr);  // 写地址（最低位为0）
    ds1302_write_byte(data);
    gpio_set_level(DS1302_RST_GPIO, 0);
    ets_delay_us(10);
}

// ds1302.c（设置时间，确保CH位清除）
esp_err_t ds1302_set_time_from_timestamp(time_t timestamp) {
    struct tm *tm_info = localtime(&timestamp);
    ds1302_write_register(DS1302_WP, 0x00);  // 关闭写保护

    // 秒（清除CH位）
    uint8_t sec_bcd = dec_to_bcd(tm_info->tm_sec) & 0x7F;
    ds1302_write_register(DS1302_SEC, sec_bcd);

    // 分、时、日、月、年
    ds1302_write_register(DS1302_MIN, dec_to_bcd(tm_info->tm_min));
    ds1302_write_register(DS1302_HR, dec_to_bcd(tm_info->tm_hour));
    ds1302_write_register(DS1302_DAY, dec_to_bcd(tm_info->tm_mday));
    ds1302_write_register(DS1302_MON, dec_to_bcd(tm_info->tm_mon + 1));
    ds1302_write_register(DS1302_YR, dec_to_bcd(tm_info->tm_year % 100));

    ds1302_write_register(DS1302_WP, 0x80);  // 开启写保护
    return ESP_OK;
}



// 获取DS1302时间（转换为Unix时间戳）
esp_err_t ds1302_get_timestamp(time_t *timestamp) {
    if (!timestamp) return ESP_ERR_INVALID_ARG;

    struct tm tm_info = {0};
    uint8_t value;

    // 读取秒（忽略CH位）
    value = ds1302_read_register(DS1302_SEC) & 0x7F;
    tm_info.tm_sec = bcd_to_dec(value);

    // 读取分
    value = ds1302_read_register(DS1302_MIN);
    tm_info.tm_min = bcd_to_dec(value);

    // 读取时（24小时制）
    value = ds1302_read_register(DS1302_HR);
    tm_info.tm_hour = bcd_to_dec(value);

    // 读取日
    value = ds1302_read_register(DS1302_DAY);
    tm_info.tm_mday = bcd_to_dec(value);

    // 读取月
    value = ds1302_read_register(DS1302_MON);
    tm_info.tm_mon = bcd_to_dec(value) - 1;

    // 读取年
    value = ds1302_read_register(DS1302_YR);
    tm_info.tm_year = bcd_to_dec(value) + 100;  // 2000年以后

    // 转换为时间戳
    *timestamp = mktime(&tm_info);

    // 打印调试信息
    ESP_LOGD("DS1302", "Read time: %04d-%02d-%02d %02d:%02d:%02d",
             tm_info.tm_year + 1900, tm_info.tm_mon + 1, tm_info.tm_mday,
             tm_info.tm_hour, tm_info.tm_min, tm_info.tm_sec);

    return ESP_OK;
}
// 初始化DS1302为默认时间（2025-05-18 00:00:00）
esp_err_t ds1302_initialize_time(void) {
    struct tm tm_info = {0};
    time_t timestamp;

    // 设置为2025年5月18日 00:00:00
    tm_info.tm_year = 125;  // 2025年（1900 + 125）
    tm_info.tm_mon = 4;     // 5月（0-11）
    tm_info.tm_mday = 18;   // 18日
    tm_info.tm_hour = 0;    // 0时
    tm_info.tm_min = 0;     // 0分
    tm_info.tm_sec = 0;     // 0秒

    // 转换为时间戳
    timestamp = mktime(&tm_info);

    // 设置DS1302时间
    return ds1302_set_time_from_timestamp(timestamp);
}